package controllers

import (
	"net/http"

	"github.com/labstack/echo"

	"zaiqiuchang.com/server/services"
)

// 响应结果结构
type response struct {
	status  int
	code    int
	message string
	context interface{}
	data    map[string]interface{}
}

// 生成响应结果
func responseJSON(c echo.Context, resp response) (err error) {
	// 如果不显示指定HTTP响应状态码，则默认为200
	if resp.status == 0 {
		resp.status = http.StatusOK
	}
	// 如果不显示指定错误描述，则使用默认的描述
	if resp.message == "" {
		resp.message = services.ErrMessages[resp.code]
	}

	// 创建标准的响应JSON结果
	respBody := map[string]interface{}{
		"code":    resp.code,
		"message": resp.message,
		"context": resp.context,
		"data":    resp.data,
	}
	c.Set("respBody", respBody)

	// 响应JSON结果
	return c.JSON(resp.status, respBody)
}

// 错误处理，保持跟正常请求一样的响应结果结构
func HttpErrorHandler(err error, c echo.Context) {
	status := http.StatusInternalServerError
	code := http.StatusInternalServerError
	msg := http.StatusText(code)
	var ctx interface{}
	// Echo框架产生的标准HTTP错误
	if he, ok := err.(*echo.HTTPError); ok {
		status = he.Code
		code = he.Code
		msg = he.Message
		// Service错误，包括HTTP响应状态码、错误码、错误描述、出错时的上下文
	} else if se, ok := err.(*services.Error); ok {
		status = http.StatusOK
		code = se.Code
		msg = services.ErrMessages[code]
		// Debug模式下输出辅助调试用的context上下文信息
		if c.Echo().Debug() {
			ctx = se.Context
		}
	}
	// Debug模式下输出具体错误描述
	if c.Echo().Debug() {
		msg = err.Error()
	}

	// 响应错误结果
	if !c.Response().Committed() {
		responseJSON(c, response{
			status:  status,
			code:    code,
			message: msg,
			context: ctx,
		})
	}

	// 记录错误日志
	c.Echo().Logger().Error(err)
}
